﻿using System;
using System.Data;

namespace JESAI.DistributedLock.Oracle;

/// <summary>
/// 实现<see cref="IDistributedLockProvider"/>以获取<see cref="OracleDistributedLock"/>，实现<see cref="IDistributedUpgradeableReaderWriterLockProvider"/>以获取<see cref="OracleDistributedReaderWriterLock"/>
/// </summary>
public sealed class OracleDistributedSynchronizationProvider : IDistributedLockProvider, IDistributedUpgradeableReaderWriterLockProvider
{
    private readonly Func<string, bool, OracleDistributedLock> _lockFactory;
    private readonly Func<string, bool, OracleDistributedReaderWriterLock> _readerWriterLockFactory;

    /// <summary>
    /// 构造一个与<paramref name="connectionString"/>和<paramref name="options"/>连接的提供程序。
    /// </summary>
    public OracleDistributedSynchronizationProvider(string connectionString, Action<OracleConnectionOptionsBuilder>? options = null)
    {
        if (connectionString == null) { throw new ArgumentNullException(nameof(connectionString)); }

        this._lockFactory = (name, exactName) => new OracleDistributedLock(name, connectionString, options, exactName);
        this._readerWriterLockFactory = (name, exactName) => new OracleDistributedReaderWriterLock(name, connectionString, options, exactName);
    }

    /// <summary>
    /// 构造一个与以下对象连接的提供程序 <paramref name="connection"/>.
    /// </summary>
    public OracleDistributedSynchronizationProvider(IDbConnection connection)
    {
        if (connection == null) { throw new ArgumentNullException(nameof(connection)); }

        this._lockFactory = (name, exactName) => new OracleDistributedLock(name, connection, exactName);
        this._readerWriterLockFactory = (name, exactName) => new OracleDistributedReaderWriterLock(name, connection, exactName);
    }

    /// <summary>
    /// 使用提供的<paramref name="name"/>创建一个<see cref="OracleDistributedLock"/>。除非指定了 <paramref name="exactName"/> ，否则将转义/散列无效名称。
    /// </summary>
    public OracleDistributedLock CreateLock(string name, bool exactName = false) => this._lockFactory(name, exactName);

    IDistributedLock IDistributedLockProvider.CreateLock(string name) => this.CreateLock(name);

    /// <summary>
    /// 使用提供的<paramref name="name"/>创建一个<see cref="OracleDistributedReaderWriterLock"/>。除非指定了<paramref name="exactName"/> ，否则将转义/散列无效名称。
    /// </summary>
    public OracleDistributedReaderWriterLock CreateReaderWriterLock(string name, bool exactName = false) => this._readerWriterLockFactory(name, exactName);

    IDistributedUpgradeableReaderWriterLock IDistributedUpgradeableReaderWriterLockProvider.CreateUpgradeableReaderWriterLock(string name) =>
        this.CreateReaderWriterLock(name);

    IDistributedReaderWriterLock IDistributedReaderWriterLockProvider.CreateReaderWriterLock(string name) =>
        this.CreateReaderWriterLock(name);
}
